package com.test.demo.gui;

import com.test.demo.RobotSimulation;
import com.test.demo.domain.*;
import com.test.demo.domain.Robot;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.embed.swing.SwingFXUtils;
import javafx.geometry.Pos;
import javafx.scene.control.Button;
import javafx.scene.control.TextArea;
import javafx.scene.image.ImageView;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.util.Duration;

import java.awt.*;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

public class CanvasGui extends BorderPane {
    private List<Robot> robots = new ArrayList<>();
    private TextArea infoText = new TextArea("信息栏");
    private Timeline timeline;
    private BufferedImage bufferedImage = new BufferedImage(RobotSimulation.width, RobotSimulation.height, BufferedImage.TYPE_INT_ARGB);
    private Graphics2D g2d;
    private ImageView imageView;
    private static CanvasGui canvasGui;

    private CanvasGui() {
        g2d = bufferedImage.createGraphics();
        // 启用抗锯齿
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

        // 启用高质量渲染
        g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);

        // 启用平滑图像插值
        g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);

        // 启用文本抗锯齿
        g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);

        imageView = new ImageView(SwingFXUtils.toFXImage(bufferedImage, null));
        imageView.setStyle("-fx-border-color: black; -fx-border-width: 1px;");
        infoText.setPrefWidth(200);
        infoText.setEditable(false);
        infoText.textProperty().addListener(new ChangeListener<String>() {
            @Override
            public void changed(ObservableValue<? extends String> observableValue, String s, String t1) {
                // 自动滚动到文本区域的底部
                infoText.setScrollTop(Double.MAX_VALUE); //this will scroll to the bottom
            }
        });

        setTop(new CustomMenuBar());
        setRight(infoText);
        setCenter(imageView);
        setBottom(bottomBtn());
        initApp();

        // 定义时间轴，周期性移动动物
        timeline = new Timeline(new KeyFrame(Duration.millis(50), e -> moveRobots()));
        timeline.setCycleCount(Timeline.INDEFINITE);

        // 监听上下左右按键按下
        setOnKeyPressed(event -> {
            int speed = 10;
            switch (event.getCode()) {
                case W:
                    controlTheHunterMovement(newRobot.getX(), newRobot.getY() - speed);
                    break;
                case S:
                    controlTheHunterMovement(newRobot.getX(), newRobot.getY() + speed);
                    break;
                case A:
                    controlTheHunterMovement(newRobot.getX() - speed, newRobot.getY());
                    break;
                case D:
                    controlTheHunterMovement(newRobot.getX() + speed, newRobot.getY());
                    break;
                case SPACE:
                    timeline.play();
                    break;
                default:
            }
        });
    }

    public static CanvasGui getInstance() {
        if (canvasGui == null) {
            canvasGui = new CanvasGui();
        }
        return canvasGui;
    }


    public void initApp() {
        // 初始化5个动物
        robots.add(new Robot1(0, 50));  // 金色
        robots.add(new Robot2(50, 100)); // 木色
        robots.add(new Robot3(100, 150)); // 土色
//        robots.add(new Robot4(150, 200));// 水色
//        robots.add(new Robot5(200, 250)); // 火色
//
        robots.add(new Robot7(100, 100)); // 火色
        robots.add(new Robot7(700, 100)); // 火色


        robots.add(new Robot7(100, 500)); // 火色
        robots.add(new Robot7(700, 500)); // 火色
        drawShape();
        moveRobots();

    }

    private void drawShape() {
        g2d.setColor(new Color(177, 202, 177, 255));
        g2d.fillRect(0, 0, RobotSimulation.width, RobotSimulation.height);

        robots.forEach(robot -> {
            if (robot.isAlive() && !robot.isBuildings()) {
                if (!robot.isHunter()) {
                    robot.randomMove();
                }
                robot.moveShape(g2d);
            } else if (robot.isBuildings() && robot.isAlive()) {
                robot.moveShape(g2d);
            }
        });
        // 更新 ImageView 显示图像
        imageView.setImage(SwingFXUtils.toFXImage(bufferedImage, null));
    }

    private void controlTheHunterMovement(int x, int y) {
        newRobot.move(x, y);
        newRobot.moveShape(g2d);
        imageView.setImage(SwingFXUtils.toFXImage(bufferedImage, null));
    }

    // 移动动物并检查相克
    private void moveRobots() {
        drawShape();

        for (int i = 0; i < robots.size(); i++) {
            if (!robots.get(i).isAlive()) continue;
            //robots.get(i).randomMove();
            drawShape();
            // 检查与其他动物相遇
            for (int j = 0; j < robots.size(); j++) {
                if (i != j && robots.get(i).isAlive() && robots.get(j).isAlive()) {
                    if (!robots.get(i).getName().equals("机器人") && !robots.get(j).getName().equals("机器人")) {
                        double distance1 = robots.get(i).getGeometry().distance(robots.get(j).getGeometry());
                        if (distance1 <= 1) { // 如果两个动物接触
                            if (robots.get(i).isBeatenBy(robots.get(j))) {
                                robots.get(j).die();
                                infoText.appendText("\n" + "动物 " + robots.get(j).getName() + " 被 " + robots.get(i).getName() + " 吃掉");
                            } else if (robots.get(j).isBeatenBy(robots.get(i))) {
                                robots.get(i).die();
                                infoText.appendText("\n" + "动物 " + robots.get(i).getName() + " 被 " + robots.get(j).getName() + " 吃掉");
                            } else {
                                // 碰撞后反向弹开
                                bounceBack(robots.get(i), robots.get(j));
                                infoText.appendText("\n" + "动物 " + robots.get(i).getName() + " 和 " + robots.get(j).getName() + " 碰撞");
                            }
                        }
                    } else {
                        if (robots.get(i).isHunter()) {
                            double distance = robots.get(i).getHalo().distance(robots.get(j).getGeometry());
                            if (distance <= 1) { // 如果两个动物接触
                                bounceBack(robots.get(i), robots.get(j));
                            }
                        }
                        // 机器人与非机器人碰撞
                        double distance1 = robots.get(i).getGeometry().distance(robots.get(j).getGeometry());
                        if (distance1 <= 1) { // 如果两个动物接触
                            if (robots.get(i).isHunter() && !robots.get(j).isHunter()) {
                                robots.get(j).die();
                                infoText.appendText("\n" + "动物 " + robots.get(j).getName() + " 被 " + robots.get(i).getName() + " 吃掉");
                            } else if (robots.get(j).isHunter() && !robots.get(i).isHunter()) {
                                robots.get(i).die();
                                infoText.appendText("\n" + "动物 " + robots.get(i).getName() + " 被 " + robots.get(j).getName() + " 吃掉");
                            }
                        }
                    }
                }
            }
        }
    }

    // 计算并反向弹开
    private void bounceBack(Robot robot1, Robot robot2) {
        // 计算两个动物之间的向量（从 robot1 到 robot2）
        double dx = robot2.getX() - robot1.getX();
        double dy = robot2.getY() - robot1.getY();

        // 计算碰撞后反向的速度
        double distance = Math.sqrt(dx * dx + dy * dy);
        double unitX = dx / distance;
        double unitY = dy / distance;

        // 将动物的速度沿着碰撞法线反向
        double bounceSpeed = 2;  // 反弹速度常量

        // 更新动物位置（为了确保它们在下一次移动时已经远离）
        if (!robot1.isHunter()) {
            robot1.setSpeed(-unitX * bounceSpeed, -unitY * bounceSpeed);
            robot1.randomMove();
        }
        if (!robot2.isHunter()) {
            robot2.setSpeed(unitX * bounceSpeed, unitY * bounceSpeed);
            robot2.randomMove();
        }
    }

    // 添加一个新的动物
    // 添加一个新的动物，并随机选择颜色
    private void addRobot() {
        // 定义颜色数组
        String[] robot = {
                "金",
                "木",
                "土",
                "水",
                "火"
        };

        // 使用 Random 随机选择一个颜色
        String robotName = robot[(int) (Math.random() * robot.length)];

        // 创建一个新的动物，位置可以设为随机或者固定位置
        Robot newRobot = buildRobot(robotName);

        // 将新动物添加到列表中
        robots.add(newRobot);

        moveRobots();

        // 更新信息栏
        infoText.appendText("\n" + "添加了动物 " + newRobot.getName() +"坐标："+ newRobot.getX() + "," + newRobot.getY());
    }

    private Robot buildRobot(String robotName) {
        switch (robotName) {
            case "金":
                return new Robot1(0, 50);
            case "木":
                return new Robot2(50, 100);
            case "土":
                return new Robot3(100, 150);
            case "水":
                return new Robot4(150, 200);
            case "火":
                return new Robot5(200, 250);
            default:
                throw new IllegalArgumentException("Invalid robot name: " + robotName);
        }
    }


    // 删除最后一个动物
    private void removeRobot() {
        if (!robots.isEmpty()) {
            List<Robot> collect = robots.stream().filter(robot -> (!robot.isBuildings() && !robot.isHunter())).collect(Collectors.toList());
            if (collect.size() == 0) {

                infoText.appendText("\n" + "没有可删除的动物 ");

                return;
            }

            robots.remove(collect.get(collect.size() - 1));
            infoText.appendText("\n" + "删除了动物 " + collect.get(collect.size() - 1).getName());
        }
    }

    // 暂停或恢复动物移动
    private void togglePause() {
        if (timeline.getStatus() == Timeline.Status.PAUSED) {
            timeline.play();
            infoText.appendText("\n" + "恢复动物移动");
        } else {
            timeline.pause();
            infoText.appendText("\n" + "暂停动物人移动");
        }
    }

    private HBox bottomBtn() {
        // 创建底部的按钮栏
        HBox bottom = new HBox();
        javafx.scene.control.Button addButton = new javafx.scene.control.Button("添加动物");
        javafx.scene.control.Button removeButton = new javafx.scene.control.Button("删除动物");
        javafx.scene.control.Button pauseButton = new javafx.scene.control.Button("暂停移动");
        javafx.scene.control.Button play = new javafx.scene.control.Button("开始");
        javafx.scene.control.Button addHunter = new Button("添加机器人");
        bottom.setAlignment(Pos.CENTER);
        bottom.setSpacing(4);
        bottom.getChildren().addAll(play, addButton, removeButton, addHunter, pauseButton);

        // 为按钮设置事件处理器
        addButton.setOnAction(e -> addRobot());
        removeButton.setOnAction(e -> removeRobot());
        pauseButton.setOnAction(e -> togglePause());
        addHunter.setOnMousePressed(e -> addHunter());
        play.setOnAction(e -> timeline.play());
        return bottom;
    }

    private Robot newRobot = new Robot6(200, 250);

    private void addHunter() {
        boolean b = robots.stream().allMatch(robot -> robot.isHunter());
        if (b) {
            infoText.appendText("\n" + "只能添加1个机器人");
            return;
        }
        // 创建一个新的动物，位置可以设为随机或者固定位置

        // 将新动物添加到列表中
        robots.add(newRobot);

        moveRobots();

        // 更新信息栏
        infoText.appendText("\n" + "添加了 " + newRobot.getName());
    }

    public List<Robot> getRobots() {
        return robots;
    }

    public void addRobots(List<Robot> robots) {
        this.robots.clear();
        Optional<Robot> aiRobot = robots.stream().filter(robot -> robot.getName().equals("机器人")).findFirst();
        if (aiRobot.isPresent()) {
            newRobot = aiRobot.get();
        }
        this.robots.addAll(robots);
        drawShape();
        moveRobots();
        infoText.appendText("\n" + "载入文件成功");
    }
}
